import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import {
  IsArray,
  IsBoolean,
  IsEnum,
  IsNumber,
  IsObject,
  IsOptional,
  IsString,
  Max,
  Min,
  ValidateNested,
} from 'class-validator';
import { Type } from 'class-transformer';

/**
 * 消息DTO
 */
export class MessageDto {
  @ApiProperty({
    description: '消息角色，如user或assistant',
    enum: ['user', 'assistant', 'system'],
    example: 'user',
  })
  @IsEnum(['user', 'assistant', 'system'])
  role: string;

  @ApiProperty({
    description: '消息内容',
    example: '你好，请告诉我今天的天气如何？',
  })
  @IsString()
  content: string;
}

/**
 * 工具函数DTO
 */
export class ToolFunctionDto {
  @ApiProperty({
    description: '函数名称',
    example: 'get_weather',
  })
  @IsString()
  name: string;

  @ApiProperty({
    description: '函数描述',
    example: '获取指定城市的天气信息',
  })
  @IsString()
  description: string;

  @ApiProperty({
    description: '函数参数定义',
    type: 'object',
  })
  @IsObject()
  parameters: Record<string, any>;
}

/**
 * 工具DTO
 */
export class ToolDto {
  @ApiProperty({
    description: '工具类型',
    example: 'function',
  })
  @IsString()
  type: string;

  @ApiProperty({
    description: '工具函数定义',
    type: ToolFunctionDto,
  })
  @ValidateNested()
  @Type(() => ToolFunctionDto)
  function: ToolFunctionDto;
}

/**
 * DeepSeek 聊天完成请求 DTO
 */
export class ChatCompletionRequestDto {
  /**
   * 消息数组，包含角色和内容
   */
  @ApiProperty({
    description: '对话消息列表',
    type: [MessageDto],
  })
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => MessageDto)
  messages: MessageDto[];

  /**
   * 模型名称
   */
  @ApiPropertyOptional({
    description: '使用的AI模型名称',
    example: 'deepseek-chat',
  })
  @IsOptional()
  @IsString()
  model?: string;

  /**
   * 频率惩罚参数
   */
  @ApiPropertyOptional({
    description: '频率惩罚，减少重复',
    minimum: -2,
    maximum: 2,
    default: 0,
    example: 0,
  })
  @IsOptional()
  @IsNumber()
  @Min(-2)
  @Max(2)
  frequency_penalty?: number;

  /**
   * 最大生成令牌数
   */
  @ApiPropertyOptional({
    description: '生成响应的最大token数',
    minimum: 1,
    maximum: 4096,
    default: 2048,
    example: 2048,
  })
  @IsOptional()
  @IsNumber()
  @Min(1)
  @Max(4096)
  max_tokens?: number;

  /**
   * 存在惩罚参数
   */
  @ApiPropertyOptional({
    description: '存在惩罚，鼓励模型讨论新主题',
    minimum: -2,
    maximum: 2,
    default: 0,
    example: 0,
  })
  @IsOptional()
  @IsNumber()
  @Min(-2)
  @Max(2)
  presence_penalty?: number;

  /**
   * 响应格式
   */
  @ApiPropertyOptional({
    description: '响应格式',
    type: 'object',
    example: { type: 'json_object' },
  })
  @IsOptional()
  @IsObject()
  response_format?: Record<string, any>;

  /**
   * 停止序列，用于结束生成
   */
  @ApiPropertyOptional({
    description: '停止生成的序列',
    type: [String],
    example: ['\n', '用户:'],
  })
  @IsOptional()
  @IsArray()
  @IsString({ each: true })
  stop?: string[];

  /**
   * 是否流式输出
   */
  stream?: boolean;

  /**
   * 流式输出选项
   */
  // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
  stream_options?: any | null;

  /**
   * 温度参数，控制生成的随机性
   */
  @ApiPropertyOptional({
    description:
      '温度参数，控制随机性（较高的值会使输出更随机，较低的值会使输出更聚焦和确定性）',
    minimum: 0,
    maximum: 2,
    default: 1,
    example: 0.7,
  })
  @IsOptional()
  @IsNumber()
  @Min(0)
  @Max(2)
  temperature?: number;

  /**
   * Top-p 参数，控制生成的多样性
   */
  @ApiPropertyOptional({
    description: 'Top-p采样，控制模型考虑的token候选集合大小',
    minimum: 0,
    maximum: 1,
    default: 1,
    example: 0.9,
  })
  @IsOptional()
  @IsNumber()
  @Min(0)
  @Max(1)
  top_p?: number;

  /**
   * 工具定义
   */
  @ApiPropertyOptional({
    description: '可用工具列表',
    type: [ToolDto],
  })
  @IsOptional()
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => ToolDto)
  tools?: ToolDto[];

  /**
   * 工具选择
   */
  @ApiPropertyOptional({
    description: '工具选择',
    type: 'object',
    example: { type: 'auto' },
  })
  @IsOptional()
  @IsObject()
  tool_choice?: any;

  /**
   * 是否返回 logprobs
   */
  @ApiPropertyOptional({
    description: '是否返回token概率日志',
    default: false,
    example: false,
  })
  @IsOptional()
  @IsBoolean()
  logprobs?: boolean;

  /**
   * top logprobs 参数
   */
  @ApiPropertyOptional({
    description: '返回的顶部token概率日志数量',
    minimum: 0,
    maximum: 20,
    example: 5,
  })
  @IsOptional()
  @IsNumber()
  @Min(0)
  @Max(20)
  top_logprobs?: number;
}
